home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk3 / 68kasm / src / a68kmain.c < prev    next >
C/C++ Source or Header  |  1995-03-18  |  20KB  |  641 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*           Copyright (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*            Main program - March 20, 1988            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*    AmigaDOS conversion copyright (c) 1988 by Charlie Gibbs.    */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. char Version[] = "1.10 (March 20, 1988)";
  24.  
  25.  
  26. #include <stdio.h>
  27. #define    PRIMARY
  28. #include "a68kdef.h"
  29. #include "a68kglb.h"
  30.  
  31.  
  32. /********************************************************************/
  33. /*                                    */
  34. /*     NOTE: the following line, plus any additional references        */
  35. /*     to _fmode, is inserted to make this program work    under        */
  36. /*     the MS-DOS version of Lattice C.     It is not necessary        */
  37. /*     for the Amiga version, but does no harm if left in.        */
  38. /*                                    */
  39. /********************************************************************/
  40. int _fmode = 0;        /* File    mode - 0x8000 for binary */
  41.  
  42.  
  43.  
  44. /* Functions */
  45. extern int  LineParts(), GetField(), Instructions(), ObjDir();
  46. extern int  GetSize(), GetInstModeSize(), GetMultReg();
  47. extern int  ReadSymTab(), GetArgs(), GetAReg(),    OpenIncl();
  48. extern long AddrBndW(),    AddrBndL(), GetValue(),    CalcValue();
  49. #ifdef AZTEC_C
  50. extern char *lmalloc();
  51. #else
  52. extern char *malloc();
  53. #endif
  54. extern FILE *fopen();
  55.  
  56.  
  57.  
  58. main(argc,argv)    int argc; char *argv[];
  59. {
  60.     char ListFN[MAXFN],    SrecFN[MAXFN], EquateFN[MAXFN];    /* File    names */
  61.     int     MakeEqu;            /* Create an equate file */
  62.     FILE *EquFile;            /* Equate file pointer */
  63.     int     keepobj;            /* Keep    object file with errors    */
  64.     int     endfile;            /* End-of-file flag */
  65.     long maxheap, maxheap2;        /* Maximum heap    sizes */
  66.     int     cmderror, dummy;
  67.     long templong, templ1, templ2, templ3;
  68.     char tempchar[MAXLINE];
  69.     register struct SymTab *sym;
  70.     register int i, j;
  71.  
  72.     cmderror = FALSE;        /* Clear command-line error flag */
  73.     SourceFN[0]    = '\0';                 /* Don't have source name yet */
  74.     HeaderFN[0]    = EquateFN[0] =    '\0';   /* No header or equate files yet */
  75.     ListFN[0] =    SrecFN[0] = '\0';       /* Indicate default file names */
  76.     InclList[0]    = '\0';         /* Clear the include directory list */
  77.     IdntName[0]    = '\0';         /* Clear program unit name */
  78.     LnMax = 60;
  79.     Quiet = 10;            /* Show    progress every 10 lines    */
  80.     XrefList = DumpSym = GotEqur = MakeEqu = KeepTabs =    keepobj    = FALSE;
  81.     SuppList = TRUE;        /* Default to no listing file */
  82.     maxheap  = DEFHEAP;        /* Primary heap    size default */
  83.     maxheap2 = DEFHEAP2;    /* Secondary heap size default */
  84.     DebugStart = 32767;    DebugEnd = 0;    /* Disable debug displays. */
  85.  
  86.     printf ("68000 Assembler - version %s\n", Version);
  87.     printf ("Copyright (c) 1985 by Brian R. Anderson\n");
  88.     printf ("AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs.\n\n");
  89.  
  90.     for    (i = 1;    i < argc; i++) {    /* Analyze command line    */
  91.     if (argv[i][0] != '-') {
  92.         if (SourceFN[0] == '\0')
  93.         strcpy (SourceFN, argv[i]);    /* Source file name */
  94.         else if (SrecFN[0] == '\0')
  95.         strcpy (SrecFN,    argv[i]);    /* Object file name */
  96.         else if (ListFN[0] == '\0')
  97.         strcpy (ListFN,    argv[i]);    /* Listing file    name */
  98.         else {
  99.         fprintf    (stderr, "Too many file names.\n");
  100.         cmderror = TRUE;
  101.         }
  102.     } else {
  103.         switch (toupper(argv[i][1])) {
  104.         case 'D':
  105.         DumpSym     = TRUE;
  106.         if (argv[i][2])    {
  107.             fprintf (stderr, "Invalid symbol table dump switch.\n");
  108.             cmderror = TRUE;
  109.         }
  110.         break;
  111.         case 'E':                           /* Equate file name */
  112.         MakeEqu    = TRUE;
  113.         if (EquateFN[0]) {
  114.             fprintf (stderr,
  115.             "Equate file is declared more than once.\n");
  116.             cmderror = TRUE;
  117.         } else if (argv[i][2])
  118.             strcpy (EquateFN, &argv[i][2]);
  119.         break;
  120.         case 'H':                           /* Header file name */
  121.         if (HeaderFN[0]) {
  122.             fprintf (stderr,
  123.             "Header file is declared more than once.\n");
  124.             cmderror = TRUE;
  125.         } else if (argv[i][2]) {
  126.             strcpy (HeaderFN, &argv[i][2]);
  127.         } else {
  128.             fprintf (stderr, "Header file name is missing\n");
  129.             cmderror = TRUE;
  130.         }
  131.         break;
  132.         case 'K':
  133.         keepobj     = TRUE;
  134.         if (argv[i][2])    {
  135.             fprintf (stderr, "Invalid object file keep switch.\n");
  136.             cmderror = TRUE;
  137.         }
  138.         break;
  139.         case 'I':                           /* Include directories */
  140.         if (argv[i][2])    {
  141.             if (InclList[0])
  142.             strcat (InclList, ","); /* Add to previous list */
  143.             strcat (InclList, &argv[i][2]);
  144.         } else {
  145.             fprintf (stderr, "Include directory list is missing.\n");
  146.             cmderror = TRUE;
  147.         }
  148.         break;
  149.         case 'L':                           /* Listing file name */
  150.         SuppList = FALSE;        /* Produce a listing */
  151.         if (ListFN[0]) {
  152.             fprintf (stderr,
  153.             "List file is declared more than once.\n");
  154.             cmderror = TRUE;
  155.         } else if (argv[i][2])
  156.             strcpy (ListFN, &argv[i][2]);
  157.         break;
  158.         case 'O':                           /* Object file name */
  159.         if (SrecFN[0]) {
  160.             fprintf (stderr,
  161.             "Object file is declared more than once.\n");
  162.             cmderror = TRUE;
  163.         } else if (argv[i][2]) {
  164.             strcpy (SrecFN, &argv[i][2]);
  165.         } else {
  166.             fprintf (stderr, "Object file name is missing\n");
  167.             cmderror = TRUE;
  168.         }
  169.         break;
  170.         case 'P':
  171.         if ((LnMax = CalcValue(&argv[i][2], 0))    < 10) {
  172.             fprintf (stderr, "Invalid page depth.\n");
  173.             cmderror = TRUE;
  174.         }
  175.         break;
  176.         case 'Q':
  177.         Quiet =    CalcValue(&argv[i][2], 0);
  178.         break;
  179.         case 'S':
  180.         SFormat    = TRUE;
  181.         if (argv[i][2])    {
  182.             fprintf (stderr, "Invalid S-format switch.\n");
  183.             cmderror = TRUE;
  184.         }
  185.         break;
  186.         case 'T':
  187.         KeepTabs = TRUE;
  188.         if (argv[i][2])    {
  189.             fprintf (stderr, "Invalid tab switch.\n");
  190.             cmderror = TRUE;
  191.         }
  192.         break;
  193.         case 'W':
  194.         if (argv[i][2] != ',') {
  195.             GetField (argv[i], 2, tempchar);
  196.             maxheap = CalcValue(tempchar, 0);
  197.             if (maxheap    < MAXLINE)
  198.             maxheap    = MAXLINE;    /* Minimum heap    size */
  199.             maxheap &= ~3L;        /* Long-word alignment */
  200.         }
  201.         for (j = 2; argv[i][j];    j++) {
  202.             if (argv[i][j] == ',') {    /* Find secondary size */
  203.             maxheap2 = CalcValue(&argv[i][j+1], 0);
  204.             if (maxheap2 < MAXLINE)    {
  205.                 maxheap2 = MAXLINE;
  206.             }
  207.             maxheap2 &= ~3L;
  208.             break;
  209.             }
  210.         }
  211.         break;
  212.         case 'X':
  213.         XrefList  = TRUE;
  214.         SuppList = FALSE;    /* We must want    a listing */
  215.         if (argv[i][2])    {
  216.             fprintf (stderr, "Invalid cross-reference switch.\n");
  217.             cmderror = TRUE;
  218.         }
  219.         break;
  220.         case 'Z':
  221.         DebugStart = 0;
  222.         DebugEnd = 32767;
  223.         if (argv[i][2] != ',') {        /* Debug dump starts here. */
  224.             GetField (argv[i], 2, tempchar);
  225.             DebugStart = CalcValue(tempchar, 0);
  226.         }
  227.         for (j = 2; argv[i][j];    j++) {
  228.             if (argv[i][j] == ',') {        /* Debug dump ends here. */
  229.             DebugEnd = CalcValue(&argv[i][j+1], 0);
  230.             if (DebugEnd ==    0)
  231.                 DebugEnd = 32767;
  232.             }
  233.         }
  234.         break;
  235.         default:
  236.         fprintf    (stderr, "Unrecognized switch.\n");
  237.         cmderror = TRUE;
  238.         break;
  239.         }
  240.     }
  241.     }
  242.  
  243.     if (SourceFN[0] == '\0') {          /* Default list file name */
  244.     fprintf    (stderr, "Source file name is missing.\n");
  245.     cmderror = TRUE;
  246.     }
  247.  
  248.     if (EquateFN[0] == '\0') {          /* Default equate file name */
  249.     strcpy (EquateFN, SourceFN);
  250.     i = strlen (EquateFN);
  251.     while (--i > 0)    {
  252.         if (EquateFN[i] == '.') {
  253.         EquateFN[i] = '\0';     /* Chop off name extension */
  254.         break;
  255.         }
  256.     }
  257.     strcat (EquateFN, ".equ");      /* Equate file name extension */
  258.     }
  259.  
  260.     if (ListFN[0] == '\0') {            /* Default list file name */
  261.     strcpy (ListFN,    SourceFN);
  262.     i = strlen (ListFN);
  263.     while (--i > 0)    {
  264.         if (ListFN[i] == '.') {
  265.         ListFN[i] = '\0';       /* Chop off name extension */
  266.         break;
  267.         }
  268.     }
  269.     strcat (ListFN,    ".lst");        /* List file name extension */
  270.     }
  271.  
  272.     if (SrecFN[0] == '\0') {            /* Default object file name */
  273.     strcpy (SrecFN,    SourceFN);
  274.     i = strlen (SrecFN);
  275.     while (--i > 0)    {
  276.         if (SrecFN[i] == '.') {
  277.         SrecFN[i] = '\0';       /* Chop off name extension */
  278.         break;
  279.         }
  280.     }
  281.     if (SFormat)
  282.         strcat (SrecFN, ".s");      /* S-format name extension */
  283.     else
  284.         strcat (SrecFN, ".o");      /* AmigaDOS format extension */
  285.     }
  286.  
  287.     if (strcmp (SourceFN, EquateFN) == 0) {
  288.     fprintf    (stderr, "Source and equate file names are the same.\n");
  289.     cmderror = TRUE;
  290.     }
  291.     if (strcmp (SourceFN, ListFN) == 0)    {
  292.     fprintf    (stderr, "Source and listing file names are the same.\n");
  293.     cmderror = TRUE;
  294.     }
  295.     if (strcmp (SourceFN, SrecFN) == 0)    {
  296.     fprintf    (stderr, "Source and object file names are the same.\n");
  297.     cmderror = TRUE;
  298.     }
  299.     if (strcmp (EquateFN, ListFN) == 0)    {
  300.     fprintf    (stderr, "Equate and listing file names are the same.\n");
  301.     cmderror = TRUE;
  302.     }
  303.     if (strcmp (EquateFN, SrecFN) == 0)    {
  304.     fprintf    (stderr, "Equate and object file names are the same.\n");
  305.     cmderror = TRUE;
  306.     }
  307.     if (strcmp (ListFN,    SrecFN)    == 0) {
  308.     fprintf    (stderr, "Listing and object file names are the same.\n");
  309.     cmderror = TRUE;
  310.     }
  311.  
  312. /*    Open Files.    */
  313.  
  314.     _fmode = 0x8000;            /******    MS-DOS only ******/
  315.     if (!cmderror) {
  316.     if ((InFile = fopen (SourceFN, "r")) == NULL) {
  317.         fprintf (stderr, "Unable to open source file.\n");
  318.         cmderror = TRUE;
  319.     }
  320.     }
  321.     _fmode = 0;                /******    MS-DOS only ******/
  322.     if (!cmderror && MakeEqu) {
  323.     if ((EquFile = fopen (EquateFN,    "w")) == NULL) {
  324.         fprintf (stderr, "Unable to open equate file.\n");
  325.         cmderror = TRUE;
  326.         fclose (InFile);        /* Close any opened files */
  327.     }
  328.     }
  329.     if (!cmderror && !SuppList)    {
  330.     if ((List = fopen (ListFN, "w")) == NULL) {
  331.         fprintf (stderr, "Unable to open listing file.\n");
  332.         cmderror = TRUE;
  333.         fclose (InFile);
  334.         if (MakeEqu)
  335.         fclose (EquFile);
  336.     }
  337.     }
  338.     if (!SFormat) _fmode = 0x8000;    /******    MS-DOS only ******/
  339.     if (!cmderror) {
  340.     if ((Srec = fopen (SrecFN, "w")) == NULL ) {
  341.         fprintf (stderr, "Unable to open object code file.\n");
  342.         cmderror = TRUE;
  343.         fclose (InFile);
  344.         if (MakeEqu)
  345.         fclose (EquFile);
  346.         if (!SuppList)
  347.         fclose (List);
  348.     }
  349.     }
  350.  
  351.     if (cmderror) {
  352.     fprintf    (stderr, "\n");
  353.     fprintf    (stderr, "Usage: a68k <source file>\n");
  354.     fprintf    (stderr, "            [-e<equate file>]\n");
  355.     fprintf    (stderr, "            [-h<header file>]\n");
  356.     fprintf    (stderr, "            [-i<include dirlist>]\n");
  357.     fprintf    (stderr, "            [-l<listing file>]\n");
  358.     fprintf    (stderr, "            [-o<object file>]\n");
  359.     fprintf    (stderr, "            [-p<page depth>]\n");
  360.     fprintf    (stderr, "            [-q[<quiet interval>]]\n");
  361.     fprintf    (stderr, "            [-w[<heap size>][,<heap size>]]\n");
  362.     fprintf    (stderr, "            [-d] [-k] [-s] [-t] [-x]\n\n");
  363.     fprintf    (stderr, "Command-line arguments can appear in any order.\n");
  364.     fprintf    (stderr, "Heap size default (bytes):  -w");
  365.     fprintf    (stderr, "%ld,%ld\n", (long) DEFHEAP, (long) DEFHEAP2);
  366.     fprintf    (stderr, "\n");
  367.     exit(20);
  368.     }
  369.  
  370. #ifdef AZTEC_C
  371.     Heap = lmalloc (maxheap);
  372. #else
  373.     Heap = malloc ((unsigned) maxheap);
  374. #endif
  375.     if (Heap ==    NULL) {
  376.     fprintf    (stderr, "Unable to allocate primary heap!\n");
  377.     exit(20);
  378.     }
  379.     HeapLim = Heap;        /* Heap    limit (start out empty)    */
  380.     LowHeap = (Heap + maxheap);
  381.     SymStart = (struct SymTab *) (LowHeap);    /* Symbol table    */
  382.  
  383. #ifdef AZTEC_C
  384.     Heap2 = lmalloc (maxheap2);
  385. #else
  386.     Heap2 = malloc ((unsigned) maxheap2);
  387. #endif
  388.     if (Heap2 == NULL) {
  389.     fprintf    (stderr, "Unable to allocate secondary heap!\n");
  390.     free (Heap);        /* Release primary heap    space */
  391.     exit(20);
  392.     }
  393.     NextFNS = Heap2;
  394.     InF    = (struct InFCtl *) (Heap2 + maxheap2);
  395.     LowInF = --InF;
  396.     InFNum = OuterMac =    SkipNest = InF->Pos = InF->MCnt    = 0;
  397.     InF->Line =    0;
  398.     InF->UPtr =    0;
  399.     InF->NPtr =    NextFNS;
  400.     InF->NArg =    -1;
  401.     strcpy (NextFNS, SourceFN);
  402.     NextFNS += strlen (SourceFN) + 1;
  403.     High2 = NextFNS;
  404.     Low2  = (char *) LowInF;
  405.  
  406.     _fmode = 0x8000;            /******    MS-DOS only ******/
  407.     printf ("Assembling %s\n\n", SourceFN);
  408.  
  409. /*-------------------------------------------------------------------
  410.  
  411.     Begin Pass 1.
  412.                                    */
  413.     fprintf (stderr, "PASS 1\n");
  414.     LineCount =    LabLine    = MacCount = ErrorCount    = NumSyms = 0;
  415.     AddrCnt = SectStart    = 0L;    /* Assume ORG =    0 to start */
  416.     CurrHunk = NextHunk    = 0L;    /* Start in hunk zero */
  417.     HunkType = HunkNone;    /* We're not in a hunk yet */
  418.     HunkFlags =    SectLine = 0;
  419.     endfile = ListOff =    MakeHunk = Pass2 = FALSE;
  420.  
  421.     /* Define ".A68K" as a SET symbol with an absolute value of 1.
  422.     This allows programs to    identify this assembler.    */
  423.     ReadSymTab (".A68K");
  424.     AddSymTab (".A68K", 1L, (long) ABSHUNK, 0, 4);
  425.  
  426.     while (!endfile && (strcmp (OpCode,    "END") != 0)) {
  427.     PrevDir    = Dir;            /* Save    previous directive */
  428.     endfile    = LineParts (dummy);    /* Get a statement */
  429.     Dir = ObjDir (Srec);        /* Process directives */
  430.     GetObjectCode (dummy);        /* Length if executable    */
  431.  
  432.     if ((HunkType == HunkNone) && (AddrAdv != 0)) {
  433.         DoSection ("", 0, "", 0, "", 0);    /* Start unnamed CODE section */
  434.         MakeHunk = TRUE;
  435.     }
  436.     if ((Label[0] != '\0')
  437.     && (Dir    != Set)    && (Dir    != Equr) && (Dir != Reg)) {
  438.         if (!ReadSymTab (Label)) {        /* Make    a new entry */
  439.         AddSymTab (Label, AddrCnt, CurrHunk, LineCount,    0);
  440.         } else if ((Sym->Flags & 1)        /* If dup., ignore */
  441.         || (Sym->Defn == NODEF)) {        /* else    fill in    */
  442.         Sym->Val = AddrCnt;        /* Current loc.    */
  443.         Sym->Hunk = CurrHunk;        /* Hunk    number */
  444.         Sym->Defn = LineCount;        /* Statement number */
  445.         Sym->Flags &= ~1;        /* Clear XREF flag */
  446.         }
  447.         if (Dir == Equ) {
  448.         Sym->Val = ObjSrc;        /* Equated value */
  449.         Sym->Hunk = Src.Hunk;        /* Hunk    number */
  450.         }
  451.     }
  452.     AddrCnt    += AddrAdv;    /* Advance location counter */
  453.     }
  454.  
  455.  
  456. /*----------------------------------------------------------------
  457.  
  458.     Begin Pass 2.
  459.                                    */
  460.     fprintf (stderr, "PASS 2\n");
  461.     InF    = (struct InFCtl *) (Heap2 + maxheap2);
  462.     InF--;
  463.     InFNum = OuterMac =    SkipNest = InF->Pos = InF->MCnt    = 0;
  464.     InF->Line =    0;
  465.     InF->UPtr =    0;
  466.     InF->NPtr =    Heap2;
  467.     InF->NArg =    -1;
  468.     fclose (InFile);            /* "Rewind" the source file */
  469.     InFile = fopen (SourceFN, "r");
  470.     NextFNS = Heap2 + strlen (SourceFN)    + 1;
  471.     Pass2 = TRUE;
  472.     LineCount =    LabLine    = MacCount = ErrorCount    = 0;
  473.     AddrCnt = CurrHunk = SectStart = EndAddr = 0L;
  474.     HunkType = HunkNone;
  475.     HunkFlags =    SectLine = 0;
  476.     endfile = ListOff =    MakeHunk = FALSE;
  477.     if ((Sym = SymStart) < (struct SymTab *) (Heap + maxheap)) {
  478.     while (Sym->Flags & 16)    {
  479.         Sym->Val = 0L;    /* Back    to start of all    sections */
  480.         Sym++;
  481.     }
  482.     }
  483.     TTLstring[0] = '\0';        /* Clear title string */
  484.     if ((templong = (HeapLim - Heap) & 3L) != 0)
  485.     HeapLim    += 4 - templong;
  486.     HighHeap = HeapLim;        /* High-water mark in heap */
  487.     RelStart = (struct RelTab *) HeapLim;    /* Relocation table */
  488.     RefStart = (struct Ref *) SymStart;    /* Cross-reference table */
  489.  
  490. /* Sign    on messages for    listing    file */
  491.     LnCnt = 999;
  492.     PgCnt = 0;
  493.     TTLstring[0] = '\0';
  494.     if (!SuppList) {
  495.     CheckPage (List, FALSE);            /* Print headings */
  496.     fprintf    (List, "68000 Cross Assembler\n");
  497.     fprintf    (List, "Copyright (c) 1985 by Brian R. Anderson\n\n");
  498.     fprintf    (List, "AmigaDOS conversion copyright (c) 1987");
  499.     fprintf    (List, " by Charlie Gibbs.\n");
  500.     fprintf    (List, "Version %s\n\n", Version);
  501.     LnCnt += 6;
  502.     }
  503.  
  504.     StartSrec (Srec, IdntName);        /* Write object    header record */
  505.  
  506. /*    Process    the second pass.    */
  507.  
  508.     OpCode[0] =    '\0';                   /* Kill "END" from pass 1! */
  509.     while (!endfile && (strcmp(OpCode,"END") != 0)) {
  510.     PrevDir    = Dir;            /* Save    previous directive */
  511.     endfile    = LineParts (dummy);    /* Get a statement */
  512.     if (!endfile) {
  513.         Dir    = ObjDir (Srec);    /* Process directives */
  514.         GetObjectCode (dummy);    /* Executable object code */
  515.         if (Label[0] != '\0') {     /* If statement is labeled, */
  516.         ReadSymTab (Label);    /*  check for duplicate    defn. */
  517.         if (Sym->Defn != LineCount) {
  518.             AddRef (LineCount);    /* Got one - flag as reference */
  519.             if (Dir == Set) {
  520.             if ((Sym->Flags    & 4) ==    0)
  521.                 Error (LabLoc, SymDup); /* Can't SET normal label */
  522.             } else {
  523.             Error (LabLoc, SymDup);    /* Ordinary duplicate */
  524.             }
  525.         } else if (Dir == Set) {
  526.             AddRef (LineCount);    /* Flag    all SETs as references */
  527.         } else {
  528.             if (Sym->Val != AddrCnt)
  529.             if ((Dir != Equ) && (Dir != Equr) && (Dir != Reg))
  530.                 Error (0, Phase);    /* Assembler error */
  531.         }
  532.         }
  533.         if (!SuppList)
  534.         WriteListLine (List);
  535.         WriteSrecLine (Srec);
  536.         AddrCnt += AddrAdv;        /* Advance locaton counter */
  537.     } else {
  538.         Error (0, EndErr);        /* END statement is missing */
  539.         if (!SuppList)
  540.         WriteListLine (List);
  541.     }
  542.     }
  543.  
  544. /*---------------------------------------------------------------------
  545.  
  546.     Clean up.
  547.                                 */
  548.  
  549.     if (HunkType != HunkNone)
  550.     Sect->Val = AddrCnt;    /* End of the last section */
  551.  
  552.     fclose (InFile);        /* Finished with source    file */
  553.  
  554.     EndSdata (Srec, EndAddr);    /* Write remaining data    and end    record */
  555.     fclose (Srec);        /* Finished with object    file */
  556.     if ((ErrorCount != 0) && (!keepobj))
  557.     unlink (SrecFN);    /* Scratch it if there were errors */
  558.  
  559.     if (XrefList)
  560.     WriteSymTab (List);    /* List    the symbol table */
  561.  
  562. /* Write all absolute symbols to an equate file    if desired. */
  563.     if (MakeEqu) {
  564.     fprintf    (EquFile, "* Equate file for %s\n", SourceFN);
  565.     fprintf    (EquFile, "* Created by A68k version %s\n", Version);
  566.     for (i = 0, sym    = SymStart; i <    NumSyms; i++, sym++) {
  567.         if (((sym->Hunk & 0x00007FFFL) == ABSHUNK)
  568.         && ((sym->Flags == 0) || (sym->Flags == 2))) {
  569.         fprintf    (EquFile, "%s\tEQU\t$", sym->Nam);
  570.         LongPut    (EquFile, sym->Val, 4);
  571.         fprintf    (EquFile, "\n");
  572.         }
  573.     }
  574.     fclose (EquFile);
  575.     }
  576.  
  577. /* Display final error count. */
  578.     fprintf (stderr, "    \nEnd of assembly - ");
  579.     if (!SuppList)
  580.     fprintf    (List, "\n\nEnd of assembly - ");
  581.     if (ErrorCount == 0) {
  582.     fprintf    (stderr, "no errors were found.\n");
  583.     if (!SuppList)
  584.         fprintf (List, "no errors were found.\n\n");
  585.     } else if (ErrorCount == 1)    {
  586.     fprintf    (stderr, "1 error was found.\n");
  587.     if (!SuppList)
  588.         fprintf (List, "1 error was found.\n\n");
  589.     } else {
  590.     fprintf    (stderr, "%d errors were found.\n", ErrorCount);
  591.     if (!SuppList)
  592.         fprintf (List, "%d errors were found.\n\n", ErrorCount);
  593.     }
  594.  
  595. /* Display heap    usage. */
  596.     templong = (long) (HighHeap    - Heap);
  597.     if (LowHeap    < (char    *) RefStart)
  598.     templong += (long) (Heap + maxheap - LowHeap);
  599.     else
  600.     templong += (long) (Heap + maxheap - (char *) RefStart);
  601.     fprintf (stderr, "Heap usage (bytes):  -w%ld", templong);
  602.     if (!SuppList)
  603.     fprintf    (List, "Heap usage (bytes):  -w%ld", templong);
  604.     templong = (long) (High2 - Heap2);
  605.     if (Low2 < (char *)    LowInF)
  606.     templong += (long) (Heap2 + maxheap2 - Low2);
  607.     else
  608.     templong += (long) (Heap2 + maxheap2 - (char *)    LowInF);
  609.     fprintf (stderr, ",%ld\n", templong);
  610.     if (!SuppList)
  611.     fprintf    (List, ",%ld\n\n", templong);
  612.  
  613. /* Display the total size of all section types.    */
  614.     templ1 = templ2 = templ3 = 0;
  615.     for    (i=0, sym=SymStart; (i<NumSyms)&&(sym->Flags&0x10); i++, sym++)    {
  616.     templong = (sym->Val + 3) & ~3L;    /* Hunk    size */
  617.     j = (sym->Hunk & 0x3FFF0000L) >> 16;    /* Hunk    type */
  618.     if (j == HunkCode)        /* Accumulate sizes by type */
  619.         templ1 += templong;
  620.     else if    (j == HunkData)
  621.         templ2 += templong;
  622.     else
  623.         templ3 += templong;
  624.     }
  625.     fprintf (stderr, "Total hunk sizes:  %lx code, ", templ1);
  626.     fprintf (stderr, "%lx data, %lx BSS\n", templ2, templ3);
  627.     if (!SuppList) {
  628.     fprintf    (List, "Total hunk sizes:  %lx code, ", templ1);
  629.     fprintf    (List, "%lx data, %lx BSS\n", templ2, templ3);
  630.     }
  631.  
  632. /* Clean up and    exit. */
  633.     if (!SuppList) {
  634.     fprintf    (List, "\f");   /* One last page eject */
  635.     fclose (List);        /* Finished with listing file */
  636.     }
  637.     free (Heap);        /* Release heap    space */
  638.     free (Heap2);
  639.     exit (ErrorCount ? 10 : 0);    /* All done */
  640. }
  641.